﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#include "Tracer.h"
#include "Tuple.h"
#include "Utils.h"
#include <stdio.h>
#include <stdlib.h>

/**
 *  \brief  元组元素构造函数
 *  \param  value 整型
 *  \return none
 */
TupleItem::TupleItem(int value)
{
    m_type = BASETYPE_INT;
    m_value = value;
    m_string = "";
}
/**
 *  \brief  元组元素构造函数
 *  \param  value 浮点型
 *  \return none
 */
TupleItem::TupleItem(double value)
{
    m_type = BASETYPE_DOUBLE;
    m_value = value;
    m_string = "";
}
/**
 *  \brief  元组元素构造函数
 *  \param  value 字符串型
 *  \return none
 */
TupleItem::TupleItem(string value)
{
    m_type = BASETYPE_STRING;
    m_string = value;
    m_value = 0;
}
/**
 *  \brief  元组元素拷贝构造函数
 *  \param  item 元组元素
 *  \return none
 */
TupleItem::TupleItem(const TupleItem& item)
{
    m_type = item.m_type;
    m_value = item.m_value;
    m_string = item.m_string;
}
/**
 *  \brief  元组元素析构函数
 *  \param  none
 *  \return none
 */
TupleItem::~TupleItem()
{
}
/**
 *  \brief  获取元组元素类型
 *  \param  none
 *  \return 共三种类型:BASETYPE_INT,BASETYPE_DOUBLE,BASETYPE_STRING.
 */
int TupleItem::baseType()
{
    return m_type;
}

/**
 *  \brief  元组元素转成int型
 *  \param  none
 *  \return 元组元素的实际类型值
 */
int TupleItem::toInt()
{
    return (int)m_value;
}
/**
 *  \brief  元组元素转成double型
 *  \param  none
 *  \return 元组元素的实际类型值
 */
double TupleItem::toDouble()
{
    return m_value;
}
/**
 *  \brief  元组元素转成string型
 *  \param  none
 *  \return 元组元素的实际类型值
 */
string TupleItem::toString()
{
    return m_string;
}

/**
 *  \brief  元组构造函数
 *  \param  none
 *  \return none
 */
Tuple::Tuple()
{
}
/**
 *  \brief  元组拷贝构造函数
 *  \param  tuple 元组
 *  \return none
 */
Tuple::Tuple(const Tuple&tuple)
{
    int num=tuple.m_valueVect.size();
    for(int i=0; i<num; i++)
    {
        TupleItem* ptv=NULL;
        switch (tuple.m_valueVect[i]->baseType())
        {
            case BASETYPE_INT:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toInt());
                m_valueVect.push_back(ptv);
                break;
            case BASETYPE_DOUBLE:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toDouble());
                m_valueVect.push_back(ptv);
                break;
            case BASETYPE_STRING:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toString());
                m_valueVect.push_back(ptv);
                break;
            default:
                break;
        }
    }
}
/**
 *  \brief  元组析构函数
 *  \param  none
 *  \return none
 */
Tuple::~Tuple()
{
    clear();
}
/**
 *  \brief  从格式化的字符串中初始化元组
 *  \param  tupleString 格式化字符串,例如:(1,"Tom",3.1415926)
 *  \return 成功返回true,失败返回false
 */
bool Tuple::initWithString(const string& tupleString)
{
    m_valueVect.clear();
    string tmpString = Utils::trimEndingBlank(tupleString);
    int strLen = tmpString.size();
    if (strLen<2 ||
        tmpString[0]!='(' ||
        tmpString[strLen-1]!=')')
    {
        return false;
    }
    int quotNum=0;
    int commaNum=0;
    int type = BASETYPE_NONE;
    string item;
    for(int i=1; i<strLen-1; i++)
    {
        if (tmpString[i]!=' ' &&
            tmpString[i]!=',' &&
            tmpString[i]!='\"')
        {
            if (commaNum!=0)
            {
                TRACE_ERR_CLASS("Invalid tuple string:%s,i=%d\n",tmpString.c_str(),i);
                return false;
            }
            item.append(1,tmpString[i]);
            continue;
        }
        if (tmpString[i]=='\"')
        {
            quotNum++;
            if (quotNum%2==0)/* 字符串结束 */
            {
                (*this)<<item.c_str();
                commaNum = 0;
                type = BASETYPE_NONE;
            }
            else /* 字符串开始 */
            {
                type = BASETYPE_STRING;
            }
            item.clear();
            continue;
        }
        else if (tmpString[i]==' ')
        {
            if (type==BASETYPE_STRING)
            {
                item.append(1,tmpString[i]);
            }
            continue;
        }
        else if (tmpString[i]==',')
        {
            if (type==BASETYPE_STRING)/* 字符串里面的逗号 */
            {
                item.append(1,tmpString[i]);
            }
            else /* 当前元素结束 */
            {
                commaNum++;
                if (commaNum<=1)
                {
                    if (!item.empty())
                    {
                        if (item.find(".")!=string::npos)
                        {
                            (*this)<<atof(item.c_str());    
                        }
                        else
                        {
                            (*this)<<atoi(item.c_str());
                        }
                    }
                    item.clear();
                    commaNum=0;
                    type=BASETYPE_NONE;
                    continue;
                }
                else
                {
                    clear();
                    return false;
                }   
            }
            continue;
        }
    }
    if (!item.empty())
    {
        if (item.find(".")!=string::npos)
        {
            (*this)<<atof(item.c_str());    
        }
        else
        {
            (*this)<<atoi(item.c_str());
        }
    }
    return true;
}

/**
 *  \brief  获取元组大小
 *  \param  none
 *  \return 元组所包含的元素的个数
 */
int Tuple::size()
{
    return m_valueVect.size();
}

/**
 *  \brief  获取类型
 *  \param  none
 *  \return BASETYPE_TUPLE
 */
int Tuple::type()
{
    return BASETYPE_TUPLE;
}

/**
 *  \brief  清空元组
 *  \param  none
 *  \return none
 */
void Tuple::clear()
{
    int num = m_valueVect.size();
    for(int i=0;i<num; i++)
    {
        DEL_OBJ(m_valueVect[i]);
    }
    return m_valueVect.clear();
}

/**
 *  \brief  序列化元组
 *  \param  none
 *  \return 序列化字符串
 */
string Tuple::serialize()
{
    string result="(";
    int num = m_valueVect.size();
    for(int i=0; i<num; i++)
    {
        switch (m_valueVect[i]->baseType())
        {
            case BASETYPE_INT:
            {
                char buf[32]={0};
                sprintf(buf,"%d",m_valueVect[i]->toInt());
                result += string(buf);
                break;
            }
            case BASETYPE_DOUBLE:
            {
                char buf[32]={0};
                sprintf(buf,"%lf",m_valueVect[i]->toDouble());
                result += string(buf);
                break;
            }
            case BASETYPE_STRING:
            {
                result += "\"";
                result += m_valueVect[i]->toString();
                result +="\"";
                break;
            }
            default:
                return "";
        }
        if (i!=(num-1))
        {
            result += ",";
        }
    }    
    result += ")";
    return result;
}

/**
 *  \brief  []运算符重载
 *  \param  none
 *  \return 返回元组元素
 */
TupleItem& Tuple::operator[](int idx)
{
    TupleItem& ret = *(m_valueVect[idx]);
    return ret;
}

/**
 *  \brief  赋值运算符重载
 *  \param  none
 *  \return 返回元组
 */
Tuple& Tuple::operator=(const Tuple& tuple)
{
    if (this==&tuple)
    {
        return (*this);
    }
    /* 清除所有元素 */
    clear();
    /* 重新拷贝tuple的元素 */
    int num = tuple.m_valueVect.size();
    for(int i=0; i<num; i++)
    {
        TupleItem* ptv=NULL;
        switch (tuple.m_valueVect[i]->baseType())
        {
            case BASETYPE_INT:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toInt());
                m_valueVect.push_back(ptv);
                break;
            case BASETYPE_DOUBLE:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toDouble());
                m_valueVect.push_back(ptv);
                break;
            case BASETYPE_STRING:
                ptv = NEW_OBJ TupleItem(tuple.m_valueVect[i]->toString());
                m_valueVect.push_back(ptv);
                break;
            default:
                break;
        }
    }
    return (*this);
}

/**
 *  \brief  <<运算符重载,实现给元组添加int型元素
 *  \param  none
 *  \return 返回元组
 */
Tuple& operator<<(Tuple& tuple,int value)
{
    TupleItem* ptv = NEW_OBJ TupleItem(value);
    tuple.m_valueVect.push_back(ptv);
    return tuple;
}
/**
 *  \brief  <<运算符重载,实现给元组添加double型元素
 *  \param  none
 *  \return 返回元组
 */
Tuple& operator<<(Tuple& tuple,double value)
{
    TupleItem* ptv = NEW_OBJ TupleItem(value);
    tuple.m_valueVect.push_back(ptv);
    return tuple;
}
/**
 *  \brief  <<运算符重载,实现给元组添加char*型元素
 *  \param  none
 *  \return 返回元组
 */
Tuple& operator<<(Tuple& tuple,const char* value)
{
    string tmp=value;
    TupleItem* ptv = NEW_OBJ TupleItem(tmp);
    tuple.m_valueVect.push_back(ptv);
    return tuple;
}
/**
 *  \brief  <<运算符重载,实现给元组添加元组元素
 *  \param  none
 *  \return 返回元组
 */
Tuple& operator<<(Tuple& tuple,TupleItem& value)
{
    TupleItem* ptv = NEW_OBJ TupleItem(value);
    tuple.m_valueVect.push_back(ptv);
    return tuple;
}
/**
 *  \brief  <<运算符重载,实现输出元组
 *  \param  none
 *  \return 返回输出流
 */
ostream& operator<<(ostream& out,Tuple& tuple)
{
    int num = tuple.size();
    out<<"Tuple:(";
    for(int i=0; i<num; i++)
    {
        switch (tuple[i].baseType())
        {
            case BASETYPE_INT:
                out<<tuple[i].toInt();
                break;
            case BASETYPE_DOUBLE:
                out<<tuple[i].toDouble();
                break;
            case BASETYPE_STRING:
                out<<"\""<<tuple[i].toString()<<"\"";
                break;
            default:
                break;
        }
        if (i!=num-1)
        {
            out<<",";
        }
    }
    out<<")\n";
    return out;
}
